#include "TSQueue.h"

template <class T>
TSQueue<T>::TSQueue(void)
{
	// Create event to block when queue is empty
	emptyEvent = CreateEvent(0, TRUE, FALSE, 0);
	notEmptyEvent = CreateEvent(0, TRUE, TRUE, 0);

	// Initialize critical section
	InitializeCriticalSectionAndSpinCount(&mCS, 0x80000400);
}

template <class T>
TSQueue<T>::~TSQueue(void)
{
	DeleteCriticalSection(&mCS);
}

template <class T>
DWORD TSQueue<T>::WaitOnEmpty(int ms=INFINITE)
{
	return WaitForSingleObject(emptyEvent, ms);
}

template <class T>
void TSQueue<T>::WaitOnNotEmpty(void)
{
	WaitForSingleObject(notEmptyEvent, INFINITE);
}

template <class T>
void TSQueue<T>::Push(const T& item)
{
	EnterCriticalSection(&mCS);

	mTaskQueue.push(item);
	SetEvent(emptyEvent);
	ResetEvent(notEmptyEvent);

	LeaveCriticalSection(&mCS);
}

template <class T>
T TSQueue<T>::Pop(void)
{
	EnterCriticalSection(&mCS);

	T task;
	// Remove a task from queue
	if(mTaskQueue.empty())
	{
		SetEvent(notEmptyEvent);
		task = mTaskQueue.front();
		mTaskQueue.pop();
	}
	else
		ResetEvent(emptyEvent); // if empty, set queue to block

	LeaveCriticalSection(&mCS);

	return task;
}

template <class T>
void TSQueue<T>::Reset(void)
{
	ResetEvent(emptyEvent);
}
